import React,{useState, useEffect, useRef} from 'react';
import * as _ from 'lodash'
import * as failImage from '@/assets/images/fail.png';
import * as loadingImage from '@/assets/images/loading.png';
import styles from './index.less';

interface ImageProps {
  src: string,
  alt?: string,
  failSrc?: string
}

const LazyloadImage: React.FC<ImageProps> = ({ src, alt='图片', failSrc= failImage  }) => {

  const [imageSrc, setImageSrc] = useState<string>(loadingImage) 
  const [loadStatus, setLoadStatus] = useState<string>('')       // 加载状态

  const imageEle = useRef<HTMLImageElement>(null)
  const imageLoaded = useRef<boolean>(false) // 图片是否已经加载过

  useEffect(() => {
    // 添加事件监听
    setImageCorrectSrc()
    window.addEventListener('scroll', _.throttle(setImageCorrectSrc,300))

    return window.removeEventListener('scroll', _.throttle(setImageCorrectSrc,300));
  },[])

  /**
   * 判读图片是否在当前视图窗口内
   */
  const checkImageInScreen = () => {
    if(imageEle.current){
      const { top, right, bottom, left } = (imageEle.current as HTMLImageElement).getBoundingClientRect()
      const clientW = window.innerWidth;
      const clientH = window.innerHeight;
      return !(top > clientH || bottom < 0 || left > clientW || right < 0)
    } else {
      return false
    }
  }

  const setImageCorrectSrc = () => {
    // 图片未加载过 并且在可视区域内时，设置为真实路径
    if(checkImageInScreen() && !imageLoaded.current){
      setImageSrc(src)
      setLoadStatus('loading')
      imageLoaded.current = true
    }
  }

  /**
   * 点击图片重新加载
   */
  const reloadImage = () => {
    if(loadStatus === 'loading') {
      return
    }
      setLoadStatus('loading')
      setImageSrc(src) 
  }

  /**
   * 图片加载成功后
   */
  const handleImageLoadSuccess = () => {
    setLoadStatus('success')
  }

  /**
   * 图片加载失败后
   */
  const handleImageLoadFail = () => {
    setLoadStatus('fail')
    setImageSrc('')
  }

  return (
    <div className={styles.container}>
      {
        ['loading','fail'].includes(loadStatus) && 
        <img className={styles.mask} onClick={reloadImage} src={loadStatus==='fail' ? failSrc : loadingImage}/>
      }
      <img 
        ref={imageEle} 
        src={imageSrc}
        onLoad={handleImageLoadSuccess}
        onError={handleImageLoadFail} 
        alt={alt}
        />
    </div>
  )
  
  
}
export default LazyloadImage;